package vsvm.data.model;

import java.io.Serializable;
import java.util.ArrayList;

import vsvm.graphics.charts.AbstractChart;
import vsvm.graphics.charts.CorrelationChart;
import vsvm.graphics.charts.GridChart;
import vsvm.graphics.charts.HistogramChart;
import vsvm.gui.Environment;
import vsvm.gui.IActionsProvider;
import vsvm.gui.IQuickInfoProvider;
import vsvm.gui.VSVMInternalFrame;
import vsvm.gui.forms.SelectFilterDialog;
import vsvm.math.statistics.histogram.Histogram;


public abstract class AbstractDataModel implements Serializable, IActionsProvider, IQuickInfoProvider {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	protected static final String AC_FILTER = "Apply filter";
	protected static final String AC_HISTOGRAM = "Histogram";
	protected static String AC_PEARSON_CORR = "Correlation matrix";
	
	protected ArrayList<AbstractAttribute> attributes;
	
	protected ArrayList<double[]> features;
	
	//protected ArrayList<Double> classes;
	protected int classIndex;
	
	protected String name;
	
	public abstract int getVectorCount();
	
	public abstract AbstractAttribute getAttribute(int index);
	
	public abstract double[] getVector(int index);
	
	public abstract double getClass(int index);
	
	public abstract double[] getAttributeData(AbstractAttribute attr);
	
	public int getAttributeCount() {
		return attributes == null ? 0 : attributes.size();
	}
	
	public void setAttributes(ArrayList<AbstractAttribute> attr) {
		attributes = attr;	
		
		// set parents
		for (int i = 0; i < attributes.size(); ++i)
			attributes.get(i).setParent(this);
	}
	
	public int getAtttributeIndex(AbstractAttribute attr) {
		for (int i = 0; i < attributes.size(); ++i)
			if (attr == attributes.get(i))
				return i;
		
		return -1;
	}
	
	
	public void setData(ArrayList<double[]> feat, int classIndex) {
		features = feat;
		this.classIndex = classIndex;
	}
	
	public boolean compatible(AbstractDataModel model) {
		return true;
	}
	
	public int getClassAttributeIndex() {
		return classIndex;
	}
	
	public abstract void setValue(double val, int index, int attr_index);
	
	public abstract double getValue(int index, int attrIndex);
	
	public String getName() { return name; }
	
	public void setName(String name) { this.name = name; }
	
	
	public String toString() {
		return name;
	}
	
	public void executeAction(String action) {
		if (action.equals(AC_FILTER)) {
			SelectFilterDialog d = new SelectFilterDialog(Environment.getEnvironment().getMainFrame(), this);
			d.setVisible(true);			
		} else if (action.equals(AC_HISTOGRAM)) {
			ArrayList <AbstractChart> charts = new ArrayList<AbstractChart>();	
			
			for (int i = 0; i < this.getAttributeCount(); i++) {
				AbstractAttribute current = this.getAttribute(i);
				charts.add(new HistogramChart(current.getName() + " attribute histogram", new Histogram(this, current)));
			}
				
			GridChart gridChart = new GridChart(charts, "All histograms");			
			Environment.getEnvironment().getMainFrame().addWindow(gridChart);
			gridChart.setVisible(true);
		} else if (action.equals(AC_PEARSON_CORR)) {
			CorrelationChart chart = new CorrelationChart(this, this.attributes);
			
			VSVMInternalFrame iframe = new VSVMInternalFrame("Correlation matrix");
			iframe.getContentPane().add(chart);
			
			
			Environment.getEnvironment().getMainFrame().addWindow(iframe);
			iframe.setVisible(true);		
			
		}
	}
	
	
	public String[] getActions() {
		return new String[]{AC_FILTER,AC_HISTOGRAM, AC_PEARSON_CORR};
	}
	
	
	public AbstractDataModel clone() {
		AbstractDataModel m = new GenericDataModel();

		m.setAttributes(attributes);
		
		ArrayList<double[]> f = new ArrayList<double[]>();
		for (int i = 0; i < features.size(); ++i) {
			double[] a = features.get(i), d = new double[a.length];
			for (int j = 0; j < a.length; ++j)
				d[j] = a[j];
			f.add(d);
		}
		m.setData(f, classIndex);
		
		return m;		
	}

}
